﻿// HSS.ServiceModel.VirtualActionOperationWithState.cs
// ----------------------------------------------------------------------------
// Licensed under the MIT license
// http://www.opensource.org/licenses/mit-license.html
// ----------------------------------------------------------------------------
// HighSpeed-Solutions, LLC
// Copyright (c) 2001-2010
// ----------------------------------------------------------------------------
// File:       VirtualActionOperationWithState.cs
// Author:     HSS\gbanta
// Created:    08/12/2010
// Modified:   12/05/2010
// ----------------------------------------------------------------------------
namespace HSS.ServiceModel
{
	#region Using Directives
	using System;
	using System.Linq.Expressions;
	using System.ServiceModel;
	#endregion

	#region VirtualActionOperation<TContract>
	/// <summary>
	/// An Action WCF Service Client that supports storing asyncronous state.
	/// </summary>
	/// <typeparam name="TContract">The Type of the WCF Service Contract.</typeparam>
	/// <typeparam name="TState">The Type of the State Object.</typeparam>
#if !DEBUG
	[System.Diagnostics.DebuggerStepThroughAttribute()]
#endif
	public sealed class VirtualActionOperation<TContract, TState> : VirtualOperation<TContract> where TContract : class
	{
		#region Constructors
		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="factoryType">The service ChannelFactory Type.</param>
		/// <param name="serviceEndpoint">The EndpointAddress of the operation.</param>
		/// <param name="serviceToken">The shared token.</param>
		public VirtualActionOperation(Type factoryType, EndpointAddress serviceEndpoint, string serviceToken)
			: base(factoryType, serviceEndpoint, serviceToken)
		{
		}
		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="factoryType">The service ChannelFactory Type.</param>
		/// <param name="serviceEndpoint">The EndpointAddress of the operation.</param>
		/// <param name="serviceToken">The shared token.</param>
		/// <param name="timeouts">The optional timeout values.</param>
		public VirtualActionOperation(Type factoryType, EndpointAddress serviceEndpoint, string serviceToken, IDefaultCommunicationTimeouts timeouts)
			: base(factoryType, serviceEndpoint, serviceToken, timeouts)
		{
		}
#if SILVERLIGHT
		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="factoryType">The service ChannelFactory Type.</param>
		/// <param name="servicePath">The virtual path that is providing accecss to VirtualServices.</param>
		/// <param name="serviceName">The Type Name for the Service (the FullName of the server side Type including it's Namespace)</param>
		/// <param name="serviceToken">The shared token.</param>
		public VirtualActionOperation(Type factoryType, string servicePath, string serviceName, string serviceToken)
			: base(factoryType, servicePath, serviceName, serviceToken)
		{
		}
		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="factoryType">The service ChannelFactory Type.</param>
		/// <param name="servicePath">The virtual path that is providing accecss to VirtualServices.</param>
		/// <param name="serviceName">The Type Name for the Service (the FullName of the server side Type including it's Namespace)</param>
		/// <param name="serviceToken">The shared token.</param>
		/// <param name="timeouts">The optional timeout values.</param>
		public VirtualActionOperation(Type factoryType, string servicePath, string serviceName, string serviceToken, IDefaultCommunicationTimeouts timeouts)
			: base(factoryType, servicePath, serviceName, serviceToken, timeouts)
		{
		}
		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="factoryType">The service ChannelFactory Type.</param>
		/// <param name="configuration">The <see cref="IChannelConfiguration"/> instance containing the Virtual Service configuration.</param>
		public VirtualActionOperation(Type factoryType, IChannelConfiguration configuration)
			: base(factoryType, configuration)
		{
		}
		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="factoryType">The service ChannelFactory Type.</param>
		/// <param name="configuration">The <see cref="IChannelConfiguration"/> instance containing the Virtual Service configuration.</param>
		/// <param name="timeouts">The optional timeout values.</param>
		public VirtualActionOperation(Type factoryType, IChannelConfiguration configuration, IDefaultCommunicationTimeouts timeouts)
			: base(factoryType, configuration, timeouts)
		{
		}
#endif
		#endregion

		#region Methods
		/// <summary>
		/// Invoke the desired operation.
		/// </summary>
		/// <param name="operation">The <see cref="Expression&lt;T&gt;"/> that defines the service operation to call.</param>
		/// <param name="callback">The completion callback.</param>
		/// <param name="userState">The user state to pass thru to the callback.</param>
		public void Invoke(Expression<Action<TContract>> operation, ChannelActionCompleted<TState> callback, TState userState)
		{
			base.BeginInvoke((MethodCallExpression)operation.Body, OnInvokeCompleted, new object[] { callback, userState });
		}
		private void OnInvokeCompleted(object state)
		{
			var args = state as InvokeAsyncCompletedEventArgs;
			var argState = args.UserState as object[];
			if (null == argState[0])
				return;
			var callBack = (ChannelActionCompleted<TState>)argState[0];
			var userState = (TState)argState[1];
			var error = args.Error;
			callBack(error, userState);
		}
		#endregion
	}
	#endregion
}